// 编译模板
class Compiler{
    constructor(el,vm){
        // 先判断是元素  还是   dom
        this.el = this.isElementNode(el)?el:document.querySelector(el);
        // 需要提取html文件的dom节点进行保存
        let fragment = this.node2fragment(this.el)

        this.vm = vm;
        // 将节点进行解析
        this.compile(fragment)
        // 将节点再来组合
        
        // 将节点在放回到html文件中去
        this.el.appendChild(fragment)
    }
    compile(node){
        let childNode_list = node.childNodes
        let node_list = [...childNode_list]
        // 查看v-model 或者{{}}
        node_list.forEach(ele=>{
            if(this.isElementNode(ele)){
                // 为节点元素
                this.compileElement(ele)  
                // 需要递归下
                this.compile(ele)

            }else{
                // 为文本
                this.compileText(ele)
            }
        })
     
       
    }
    // 判断v-开头的
    isDirective(attrName){
        return attrName.startsWith('v-')
    }
    // 编译节点 查询v-model
    compileElement(node){
        // console.log(node)
        let attributes = node.attributes;
        [...attributes].forEach(attr=>{
            // 结构方法
            let {name,value:expr}  = attr;
            // console.log(name,expr)
            if(this.isDirective(name)){
                let [,directive] = name.split("-")
                // 需要去做解析
                CompileUtil[directive](node,expr,this.vm)
            }
        })
    }
    // 编译文本  查询文本中的{{}}
    compileText(node){
        let content = node.textContent;
        if(/\{\{(.+?)\}\}/.test(content)){
            CompileUtil['text'](node,content,this.vm)
        }
    }
    // 将节点保存在容器中去
     node2fragment(node){
        // 创建一个容器
        let fragment = document.createDocumentFragment()
        let firstChild 
        while (firstChild = node.firstChild) {
            fragment.appendChild(firstChild)
        }
        return fragment
    }
    // 判断是不是dom
    isElementNode(node){
        return node.nodeType === 1;
    }
   
}
// 建立替换数据  和  将dom元素还原
CompileUtil = {
    getVal(vm,expr){
        return expr.split(".").reduce((data,current)=>{
            return data[current]
        },vm.$data)
    },
    model(node,expr,vm){
        let fn = this.updater['modelUpdater']
        let value = this.getVal(vm,expr) //珠峰
        fn(node,value)            
    },
    html(){
        // 把html    node.innerHTMl
    },
    text(node,expr,vm){
        // expr {{a}}  {{b}}
        let fn = this.updater['textUpdater']
        let content = expr.replace(/\{\{(.+?)\}\}/g,(...args)=>{
            return this.getVal(vm,args[1])
        })
        fn(node,content)
    },
    updater:{
        modelUpdater(node,value){
            // 输入框  就是node.value = value
            node.value = value
        },
        htmlUpdater(node,value){
            node.innerHTML = value;
        },
        textUpdater(node,value){
            node.textContent = value
        },

    },


}



class Vue{
    constructor(options){
        this.$el = options.el;
        this.$data = options.data;
    // 根元素  
        if(this.$el){
            new Compiler(this.$el,this)
        }
    }
    
}

